//promise并发执行
if (!Promise.allSettled) {
    Promise.allSettled = promises =>
        Promise.all(
            promises.map((promise, i) =>
                promise
                    .then(value => ({
                        status: "fulfilled",
                        value,
                    }))
                    .catch(reason => ({
                        status: "rejected",
                        reason,
                    }))
            )
        );
}

//https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled

async function operation(v) {
    let ts = parseInt(Math.random() * 10000);
    console.log('操作时间：', ts);
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(v * 2);
        }, ts);
    });
}

async function parallel(data, func, def = {}) {
    if (Array.isArray(data)) {
        let result = await Promise.allSettled(typeof (func) == 'function' ? data.map(func) : data);
        let t = [];
        for (let r of result) {
            if (r.status == 'fulfilled') {
                t.push(r.value);
            } else {
                t.push(def);
            }
        }
        return t;
    } else {
        let keys = Object.keys(data);
        let values = Object.values(data);
        let result = await Promise.allSettled(typeof (func) == 'function' ? values.map(func) : values);
        let t = {};
        for (let [i, r] of result.entries()) {
            if (r.status == 'fulfilled') {
                t[keys[i]] = r.value;
            } else {
                t[keys[i]] = def;
            }
        }
        return t;
    }
}

async function parallelSimple(data, elements) {
    let arr = [];
    let keys = Object.keys(elements);
    let values = Object.values(elements);
    let entries = Object.entries(elements);
    //封装promise数组
    for (let d of data) {
        for (let e of entries) {
            let k = e[0];
            let fn = e[1][0];
            let v = e[1].slice(1);
            arr.push(fn(...v.map(vv => eval('(' + vv + ')'))));//d[vv]
        }
    }
    //执行
    let result = await Promise.allSettled(arr);
    let tmp = [];
    for (let r of result) {
        if (r.status == 'fulfilled') {
            tmp.push(r.value);
        } else {
            tmp.push('');
        }
    }
    //切割结果
    let r = [];
    for (let i = 0; i < tmp.length; i += keys.length) {
        r.push(tmp.slice(i, i + keys.length));
    }
    //合并数据
    for (let [i, d] of data.entries()) {
        for (let [index, key] of keys.entries()) {
            d[key] = r[i][index];
        }
    }
    return data;
}

async function getBasedata(d) {
    return `我是所有promise都需要的:${d.id}`;
}

async function getUsername(userid, title = '', id = '') {
    let map = {
        100: '张三',
        200: '李四',
        300: '王五',
    };
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(map[userid] + title + id);
        }, 2000);
    });
}
async function getCatname(catid, other = []) {
    let map = {
        4: '娱乐',
        7: '体育',
        8: '军事',
        10: '国际',
        11: '财经',
    };
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(map[catid] + other);
        }, 1000);
    });
}
async function getAddtime(addtime, other = {}, basedata = '') {
    return new Date(addtime * 1000).toLocaleDateString() + JSON.stringify(other) + basedata;
}

//一个并发
async function commonStart() {
    console.time('a');
    let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    for (let d of data) {
        console.log(await operation(d));
    }
    console.timeEnd('a');
}
//多个并发
async function parallelStart() {
    console.time('b');
    let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    // let result = await Promise.allSettled(data.map(operation));
    let result = await parallel(data, operation, 0);
    console.log(result);
    console.timeEnd('b');
}

//模拟数据库查询
async function parallelDbOld() {
    console.time('c');
    let data = [
        {
            id: 1,
            title: '卖保险不如送外卖？百万保险代理人“消失”背后',
            userid: 100,
            catid: 8,
            addtime: 1638065254,
        },
        {
            id: 2,
            title: '德克士一线城市关店，“县城顶流”还是难进北上广？',
            userid: 200,
            catid: 10,
            addtime: 1638065254,
        },
        {
            id: 3,
            title: '运-20出动！十多万套新型过冬被装上高原',
            userid: 300,
            catid: 7,
            addtime: 1638065254,
        },
        {
            id: 4,
            title: '供应链瓶颈、劳动力短缺，圣诞老人可能去不了美国人的圣诞节了',
            userid: 100,
            catid: 4,
            addtime: 1638065254,
        },
        {
            id: 5,
            title: '猴子闯进高校课堂抢走学生豆浆，网友：可能天冷想暖暖身子',
            userid: 300,
            catid: 11,
            addtime: 1638065254,
        },
    ];
    for (let d of data) {
        d.username = await getUsername(d.userid);
        d.catname = await getCatname(d.catid);
        d.addtime = await getAddtime(d.addtime);
    }
    console.log(data);
    console.timeEnd('c');
}

async function parallelDbNew() {
    console.time('d');
    let data = [
        {
            id: 1,
            title: '卖保险不如送外卖？百万保险代理人“消失”背后',
            userid: 100,
            catid: 8,
            addtime: 1638065254,
        },
        {
            id: 2,
            title: '德克士一线城市关店，“县城顶流”还是难进北上广？',
            userid: 200,
            catid: 10,
            addtime: 1638065254,
        },
        {
            id: 3,
            title: '运-20出动！十多万套新型过冬被装上高原',
            userid: 300,
            catid: 7,
            addtime: 1638065254,
        },
        {
            id: 4,
            title: '供应链瓶颈、劳动力短缺，圣诞老人可能去不了美国人的圣诞节了',
            userid: 100,
            catid: 4,
            addtime: 1638065254,
        },
        {
            id: 5,
            title: '猴子闯进高校课堂抢走学生豆浆，网友：可能天冷想暖暖身子',
            userid: 300,
            catid: 11,
            addtime: 1638065254,
        },
    ];
    data = await parallel(data, async (d) => {
        d.basedata = await getBasedata(d);
        return d;
    });
    data = await parallel(data, async (d) => {
        let r = await parallel({ username: getUsername(d.userid), catname: getCatname(d.catid), addtime: getAddtime(d.addtime, { a: 1, b: 2 }, d.basedata) }, null, '');
        return Object.assign(d, r);
    });
    console.log(data);
    console.timeEnd('d');
}


global.title = '【教授】';
console.log(title, global.title);
async function parallelDbSimple() {
    console.time('e');
    let data = [
        {
            id: 1,
            title: '卖保险不如送外卖？百万保险代理人“消失”背后',
            userid: 100,
            catid: 8,
            addtime: 1638065254,
        },
        {
            id: 2,
            title: '德克士一线城市关店，“县城顶流”还是难进北上广？',
            userid: 200,
            catid: 10,
            addtime: 1638065254,
        },
        {
            id: 3,
            title: '运-20出动！十多万套新型过冬被装上高原',
            userid: 300,
            catid: 7,
            addtime: 1638065254,
        },
        {
            id: 4,
            title: '供应链瓶颈、劳动力短缺，圣诞老人可能去不了美国人的圣诞节了',
            userid: 100,
            catid: 4,
            addtime: 1638065254,
        },
        {
            id: 5,
            title: '猴子闯进高校课堂抢走学生豆浆，网友：可能天冷想暖暖身子',
            userid: 300,
            catid: 11,
            addtime: 1638065254,
        },
    ];
    //basedata
    data = await parallelSimple(data, { basedata: [getBasedata, 'd'] });
    data = await parallelSimple(data, { userid_title: [getUsername, 'd.userid', 'global.title', 'd.id', 'd.basedata'], catname: [getCatname, 'd.catid', '[1,2,3]'], addtime: [getAddtime, 'd.addtime', '{a:1,b:2}', 'd.basedata'] });
    console.log(data);
    console.timeEnd('e');
}

async function parallelDbSimple2() {
    console.time('f');
    let data = [
        {
            id: 1,
            title: '卖保险不如送外卖？百万保险代理人“消失”背后',
            userid: 100,
            catid: 8,
            addtime: 1638065254,
        },
        {
            id: 2,
            title: '德克士一线城市关店，“县城顶流”还是难进北上广？',
            userid: 200,
            catid: 10,
            addtime: 1638065254,
        },
        {
            id: 3,
            title: '运-20出动！十多万套新型过冬被装上高原',
            userid: 300,
            catid: 7,
            addtime: 1638065254,
        },
        {
            id: 4,
            title: '供应链瓶颈、劳动力短缺，圣诞老人可能去不了美国人的圣诞节了',
            userid: 100,
            catid: 4,
            addtime: 1638065254,
        },
        {
            id: 5,
            title: '猴子闯进高校课堂抢走学生豆浆，网友：可能天冷想暖暖身子',
            userid: 300,
            catid: 11,
            addtime: 1638065254,
        },
    ];
    //basedata
    data = await parallelSimple(data, { basedata: [getBasedata, 'd'] });
    data = await parallelSimple(data, { userid_title: [getUsername, 'd.userid', 'global.title', 'd.id', 'd.basedata'] });
    data = await parallelSimple(data, { catname: [getCatname, 'd.catid', '[1,2,3]'] });
    data = await parallelSimple(data, { addtime: [getAddtime, 'd.addtime', '{a:1,b:2}', 'd.basedata'] });
    console.log(data);
    console.timeEnd('f');
}

// commonStart();
// parallelStart();
// parallelDbOld();
// parallelDbNew();
parallelDbSimple();
parallelDbSimple2();
